//
//  Level2Layer.m
//
//  Source file for the class where all aspects of the second level
//  of the game is implemented.
//

#import "LevelLayer.h"
#import "Level2Layer.h"
#import "Level3Layer.h"
#import "AppDelegate.h"
#import "MainMenuLayer.h"
#import "GameState.h"
#import "SimpleAudioEngine.h"

static const int kTimerLabelSize = 64;
static const int kHeightOffset = 94;
static const int kTotalDistractions = 26;
static const int kAllWantedObjects = 19;
static const int kTotalWantedObjects = 3;
static const int kDefaultTimer = 60;
static const int kWantedObject = 1;
static const int kUnWantedObject = 0;
static const int kMainMenuButton = 0;
static const int kRetryButton = 1;
static int pauseButton = 0;


@implementation Level2Layer

// returns a scene object containing the current layer
// this essentially loads the "screen" for a
// particular section or part of the game
+(CCScene *) scene
{
	CCScene *scene = [CCScene node];
    Level2Layer *layer = [Level2Layer node];
    
	[scene addChild: layer];
	
	return scene;
}

// implements the main game logic which is when the player
// touches an object, the score is adjusted based on whether
// the object touched is a wanted or unwanted object
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [self convertTouchToNodeSpace:touch];
    
    // a list of screen objects to delete. this list is needed as opposed to
    // deleting straight from currentScreenObjects because objective-c does not
    // allow the mutation of a NSMutableArray while it is being enumerated (i.e. iterated over)
    NSMutableArray *screenObjectsToDelete = [[NSMutableArray alloc] init];
    
    // when a touch is registered, go through all the objects currently on screen
    // and if a wanted object is touched, add it to the list of objects to be removed from
    // the screen. if a distraction is touched, it will wiggle and resume its normal action
    for (CCSprite *screenObj in _currentScreenObjects) {
        if (CGRectContainsPoint(screenObj.boundingBox, location)) {
            if (screenObj.tag == kWantedObject) {
                [_scoreLabel setString:[NSString stringWithFormat:@"%d", [[GameState sharedGameState] incScore]]];
                [[SimpleAudioEngine sharedEngine] playEffect:@"146721__fins__menu-click.wav"];
                
                [screenObjectsToDelete addObject:screenObj];
                
            }
            else if (screenObj.tag == kUnWantedObject) {
                [_scoreLabel setString:[NSString stringWithFormat:@"%d", [[GameState sharedGameState] decScore]]];
                [screenObj runAction:[CCSequence actions:[CCRotateBy actionWithDuration:0.3 angle:20], [CCRotateBy actionWithDuration:0.3 angle:-40], [CCRotateBy actionWithDuration:0.3 angle:20], nil]];
                [[SimpleAudioEngine sharedEngine] playEffect:@"171526__fins__old-reactor.wav"];
            }
            
            // this tag assignment is needed to prevent the score from being
            // updated more than once
            screenObj.tag = 2;
        }
    }
    
    for (CCSprite *objToDelete in screenObjectsToDelete) {
        
        // before an object disappears from screen, show a quick animation of it
        // moving slightly up and then down
        CCMoveTo * moveUp = [CCMoveTo actionWithDuration:0.2
                                                position:ccp(objToDelete.position.x, objToDelete.position.y + 20)];
        
        CCMoveTo * moveDown = [CCMoveTo actionWithDuration:0.5
                                                  position:ccp(objToDelete.position.x, 0)];
        
        CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock:^(CCNode *node) {
            [_currentScreenObjects removeObject:objToDelete];
            [node removeFromParentAndCleanup:YES];
        }];
        
        [objToDelete runAction:[CCSequence actions:moveUp, moveDown, actionMoveDone, nil]];
    }
    
    [screenObjectsToDelete release];
}

// this is the method that handles the button press functionality of the alert box
// that pops up when the game ends or when the user progresses to the next level
-(void) alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [[CCDirector sharedDirector] resume];
    
    // the user presses the first button main menu which aborts the game 
    // the score and data from that game are saved
    if (buttonIndex == kMainMenuButton) {
        [[GameState sharedGameState] setState:@"totalScore" value:[[GameState sharedGameState] getScore]+[[[GameState sharedGameState] getState:@"totalScore"] integerValue]];
        [[GameState sharedGameState] setState:@"totalGamesPlayed" value:1+[[[GameState sharedGameState] getState:@"totalGamesPlayed"] integerValue]];
        [[GameState sharedGameState] saveHighestScore];
        [[GameState sharedGameState] resetScore];
        [[GameState sharedGameState] resetCompletion];
        [[CCDirector sharedDirector] replaceScene:[MainMenuLayer scene]];
    }
    // the user presses the second button, and no time is remaining,
    // implies the user has lost the game, the score and data are saved
    else if (buttonIndex == kRetryButton && _currentTime == 0) {
        [[GameState sharedGameState] setState:@"totalScore" value:[[GameState sharedGameState] getScore]+[[[GameState sharedGameState] getState:@"totalScore"] integerValue]];
        [[GameState sharedGameState] setState:@"totalGamesPlayed" value:1+[[[GameState sharedGameState] getState:@"totalGamesPlayed"] integerValue]];
        [[GameState sharedGameState] saveHighestScore];
        [[GameState sharedGameState] resetScore];
        [[GameState sharedGameState] resetCompletion];
        [[CCDirector sharedDirector] replaceScene:[LevelLayer scene]];
    }
    // the user presses the second button with time remaining,
    // implies that the user wants to resume the game
    else if (buttonIndex == kRetryButton && _currentTime != 0 && pauseButton != 0){
        pauseButton = 0;
    }
    // the user presses the second button with time remaining, implies that
    // the user has the required amount of points and wants to progress to next level
    else if (buttonIndex == kRetryButton && _currentTime != 0) {
        [[GameState sharedGameState] incCompletion];
        [[CCDirector sharedDirector] replaceScene:[Level3Layer scene]];
    }
}

// this method is called every 1 second to update the amount of
// time left for this level
-(void) gameTimer
{
    [_timeLabel setString:[NSString stringWithFormat:@"%d", --_currentTime]];
    
    if (_currentTime == 0) {
        [[CCDirector sharedDirector] pause];
        [[GameState sharedGameState] setState:@"totalTimePlayed" value:60+[[[GameState sharedGameState] getState:@"totalTimePlayed"] integerValue]];
        UIAlertView *dialog = [[UIAlertView alloc] init];
        [dialog setDelegate:self];
        [dialog setTitle:@"Times Up!"];
        [dialog setMessage:[NSString stringWithFormat:@"Your high score is: %d", [[GameState sharedGameState] getScore]]];
        [dialog addButtonWithTitle:@"Main Menu"];
        [dialog addButtonWithTitle:@"Retry"];
        [dialog show];
        [dialog release];
    }
}

// this method is called every tenth of a second to check if 5 points has been
// accumulated in this level, in which case the player moves on to the next level
-(void) scoreCheck
{
    if ([[GameState sharedGameState] getScore] == 5*([[GameState sharedGameState] getCompletion] + 1)) {
        [[CCDirector sharedDirector] pause];
        
        // check if the time taken to complete this level is a record best 
        // time for the user, if so, update the best time
        int bestTime = [[[GameState sharedGameState] getState:@"level2BestTime"] integerValue];
        if (60-_currentTime < bestTime) {
            [[GameState sharedGameState] setState:@"level2BestTime" value:60-_currentTime];
        }
        
        // adds the time taken to complete this level to the total time played
        [[GameState sharedGameState] setState:@"totalTimePlayed" value:60-_currentTime+[[[GameState sharedGameState] getState:@"totalTimePlayed"] integerValue]];
        
        UIAlertView *dialog = [[UIAlertView alloc] init];
        [dialog setDelegate:self];
        [dialog setTitle:@"Congratulations!"];
        [dialog setMessage:[NSString stringWithFormat:@"You've reached the next level!"]];
        [dialog addButtonWithTitle:@"Main Menu"];
        [dialog addButtonWithTitle:@"Continue"];
        [dialog show];
        [dialog release];
    }
}

-(void)pausePressed
{
    pauseButton = 1;
    [[CCDirector sharedDirector] pause];
    UIAlertView *dialog = [[UIAlertView alloc] init];
    [dialog setDelegate:self];
    [dialog setTitle:@"Level 2"];
    [dialog setMessage:[NSString stringWithFormat:@"You have paused the game"]];
    [dialog addButtonWithTitle:@"Main Menu"];
    [dialog addButtonWithTitle:@"Resume"];
    [dialog show];
    [dialog release];
    
    
    
    
}

// this method is called every 2 seconds and adds a suitcase with objects that can
// be tapped by the player
-(void) addSuitcase
{
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    CCSprite *suitcase = [CCSprite spriteWithFile:@"suitcase.png"];
    suitcase.position = ccp(-suitcase.contentSize.width / 2, winSize.height/2);
    
    NSMutableArray *suitcaseObjects = [[NSMutableArray alloc] init];
    
    // randomly choose 9 objects for the suitcase, with a set probability of having a wanted object
    int wantedCount = 0;
    for (int i=1; i<10; i++){
        int wantedChance = arc4random() % 10;
        if (wantedChance == 0) {
            wantedCount++;
            NSString *randomPick = [_wantedObjects objectAtIndex:(arc4random() % kTotalWantedObjects)];
            CCSprite *levelObj = [CCSprite spriteWithFile:randomPick];
            levelObj.tag = 1;
            [suitcaseObjects addObject:levelObj];
        }
        else {
            NSString *randomPick = [_distractionObjects objectAtIndex:(arc4random() % (kTotalDistractions))];
            CCSprite *levelObj = [CCSprite spriteWithFile:randomPick];
            levelObj.tag = 0;
            [suitcaseObjects addObject:levelObj];
        }
    }
    
    // add all suitcase objects offscreen (they will wait until suitcase is in scanner)
    // the counter determines where in the grid the object should be placed
    int counter = 0;
    for (CCSprite *levelObj in suitcaseObjects) {
        levelObj.position = ccp((counter%3)*150-150+winSize.width/2,(floor(counter/3))*120+880+winSize.height/2);
        [_currentScreenObjects addObject:levelObj];
        counter++;
        [self addChild:levelObj z:3];
    }
    
    // use the wanted count to determine whether or not the suitcase is safe
    // if the suitcase is safe, then the player can tap the button for a point
    CCSprite *safeButton = [CCSprite spriteWithFile:@"fastforwardbutton.png"];
    if (wantedCount == 0){
        safeButton.tag = 1;
    }
    else{
        safeButton.tag = 0;
    }
    // add the button to the list of objects to be tapped offscreen
    [_currentScreenObjects addObject:safeButton];
    safeButton.position = ccp(winSize.width/2,800+winSize.height/2);
    [self addChild:safeButton z:3];
    
    CCSprite *scannerBackground = [CCSprite spriteWithFile:@"level2ScannerBackground.png"];
    scannerBackground.position = ccp(winSize.width/2,winSize.height+scannerBackground.contentSize.height/2);
    [self addChild:scannerBackground z:2];
    
    [self addChild:suitcase z:1];
    
    
    int moveDuration = 1.0;
    float scanDuration = (3.0-0.3*floor([[GameState sharedGameState] getCompletion]/3));
    if (scanDuration < 0.6){
        scanDuration = 0.6;
    }
    
    CCMoveTo * suitcaseMoveRight1 = [CCMoveTo actionWithDuration:moveDuration
                                                        position:ccp(winSize.width/2, winSize.height/2)];
    CCMoveTo * suitcaseMoveRight2 = [CCMoveTo actionWithDuration:moveDuration
                                                        position:ccp(winSize.width+suitcase.contentSize.width / 2, winSize.height/2)];
    
    CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock:^(CCNode *node) {
        [node removeFromParentAndCleanup:YES];
    }];
    
    // this will be called when the scan ends, the suitcase objects
    // are removed from the list of objects that can be tapped
    CCCallBlockN * actionMoveDone2 = [CCCallBlockN actionWithBlock:^(CCNode *node) {
        for (CCSprite *levelObj in suitcaseObjects) {
            [_currentScreenObjects removeObject:levelObj];
        }
        [_currentScreenObjects removeObject:safeButton];
        [node removeFromParentAndCleanup:YES];
    }];
    
    CCDelayTime * movePause = [CCDelayTime actionWithDuration:moveDuration];
    CCDelayTime * scanPause = [CCDelayTime actionWithDuration:scanDuration];
    
    CCAction * hideObject = [CCHide action];
    CCAction * showObject = [CCShow action];
    
    [suitcase runAction:[CCSequence actions:suitcaseMoveRight1, scanPause, suitcaseMoveRight2, actionMoveDone, nil]];
    
    // the objects associated with each suitcase is initially hidden,
    // they will appear in the suitcase when the suitcase stops
    // (i.e. when the scanner is activated)
    for (CCSprite *levelObj in suitcaseObjects) {
        [levelObj runAction:[CCSequence actions: [CCDelayTime actionWithDuration:0.01],hideObject, movePause, [CCMoveTo actionWithDuration:0.01
                                position:ccp(levelObj.position.x,levelObj.position.y-1000)], showObject, scanPause, actionMoveDone,nil]];
    }
    
    [safeButton runAction:[CCSequence actions: [CCDelayTime actionWithDuration:0.01],hideObject, movePause, [CCMoveTo actionWithDuration:0.01                                                                                                                              position:ccp(safeButton.position.x,safeButton.position.y-1000)], showObject, scanPause, actionMoveDone,nil]];
    
    [scannerBackground runAction:[CCSequence actions: [CCDelayTime actionWithDuration:0.01],hideObject, movePause, [CCMoveTo actionWithDuration:0.01                                                                                                                              position:ccp(winSize.width/2,winSize.height/2)], showObject, scanPause, actionMoveDone2,nil]];
    
    [suitcaseObjects release];
}

// initialize this layer; this includes initializing several instance variables
// and initializing the sprites needed for this scene
-(id) init
{
	if( (self = [super init]) ) {
        
        // list of all images that we have for this level
        _distractionObjects = [[NSArray arrayWithObjects:@"blowdryer.png", @"boots.png", @"bowtie.png", @"clothes1.png", @"clothes2.png", @"clothes3.png", @"clothes4.png", @"clothes5.png", @"clothes6.png", @"comb1.png", @"comb2.png", @"comb3.png", @"comb4.png", @"comb5.png", @"comb6.png", @"glasses.png", @"highheel.png", @"necklace.png", @"paperclip.png", @"scissors1.png", @"scissors2.png", @"skates.png", @"sunglasses.png", @"umbrella.png", @"utensils.png", @"wrench.png", nil] retain];
        _allWantedObjects = [[NSArray arrayWithObjects:@"bottle1.png", @"bottle2.png", @"bottle3.png", @"bottle4.png", @"gascontainer.png", @"hammer.png", @"knife1.png", @"knife2.png", @"knife3.png", @"leaf1.png", @"leaf2.png", @"leaf3.png", @"leaf4.png", @"leaf5.png", @"needle.png", @"pistol1.png", @"pistol2.png", @"rifle.png", @"spraybottle.png", nil] retain];
        
        _currentScreenObjects = [[NSMutableArray alloc] init];
        _wantedObjects = [[NSMutableArray alloc] init];
        
        CGSize winSize = [[CCDirector sharedDirector] winSize];
        int posMultiplier = 1;
        int wantedPosX;
        int wantedPosY;
        
        // randomly populate the list of wanted objects until there are three elements in total.
        while(_wantedObjects.count != kTotalWantedObjects) {
            NSString *randomPick = [_allWantedObjects objectAtIndex:(arc4random() % kAllWantedObjects)];
            
            if ([_wantedObjects containsObject:randomPick]) {
                continue;
            }
            else {
                [_wantedObjects addObject:randomPick];
            }
        }
                
        // after each pick, display the object at the bottom of the screen
        for ( int i=1; i < kTotalWantedObjects+1; i++) {
            CCSprite *wantedSprite = [CCSprite spriteWithFile:[_wantedObjects objectAtIndex:(i-1)]];
            wantedPosX = winSize.width/2 + 200 * (posMultiplier-(kTotalWantedObjects+1)/2);
            wantedPosY = 70;
            wantedSprite.position = ccp( wantedPosX, wantedPosY);
            ++posMultiplier;
            [self addChild:wantedSprite z:1];
        }
        
        CCSprite *bg = [CCSprite spriteWithFile:@"scanner.png"];
        bg.position = ccp(winSize.width / 2, winSize.height / 2);
        [self addChild:bg z:0];
        
        _currentTime = kDefaultTimer;
        _timeLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%d", kDefaultTimer] fontName:@"Marker Felt" fontSize:kTimerLabelSize];
		_timeLabel.position =  ccp(winSize.width - kTimerLabelSize, winSize.height - kTimerLabelSize);
        _timeLabel.color = ccc3(0, 0, 0);
		[self addChild: _timeLabel];
        
        _scoreLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%d", [[GameState sharedGameState] getScore]] fontName:@"Marker Felt" fontSize:kTimerLabelSize];
        _scoreLabel.position = ccp(kTimerLabelSize / 2, winSize.height - kTimerLabelSize);
        _scoreLabel.color = ccc3(0, 0, 255);
        [self addChild: _scoreLabel];
        
        CCMenuItemImage *pauseBtn = [CCMenuItemImage itemWithNormalImage:@"pausebutton.png"
                                                           selectedImage:@"pausebutton.png" target:self selector:@selector(pausePressed)];
        
        //the pause button will be placed on the bottom right of the screen
        CCMenu *pauseMenu = [CCMenu menuWithItems:pauseBtn, nil];
        
        pauseMenu.position = ccp(950, 62.5);
        
        [self addChild:pauseMenu];
        
        self.touchEnabled = YES;
        [self schedule:@selector(gameTimer) interval:1.0];
        [self schedule:@selector(scoreCheck)];
        [self schedule:@selector(addSuitcase) interval:4.0];
	}
    
	return self;
}

// deallocate all memory used
- (void) dealloc
{
    [_distractionObjects release];
    [_wantedObjects release];
    [_currentScreenObjects release];
    _distractionObjects = nil;
    _wantedObjects = nil;
    _currentScreenObjects = nil;
	[super dealloc];
}

#pragma mark GameKit delegate

@end